package com.yangaobo.service.impl;

import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.bean.copier.CopyOptions;
import cn.hutool.core.util.ObjectUtil;
import cn.hutool.core.util.StrUtil;
import com.github.pagehelper.PageHelper;
import com.github.pagehelper.PageInfo;
import com.yangaobo.dto.AssetsBorrowInsertDTO;
import com.yangaobo.dto.AssetsBorrowPageDTO;
import com.yangaobo.dto.AssetsBorrowUpdateDTO;
import com.yangaobo.entity.Assets;
import com.yangaobo.entity.AssetsBorrow;
import com.yangaobo.excel.AssetsBorrowExcel;
import com.yangaobo.exception.IllegalParamException;
import com.yangaobo.exception.ServerErrorException;
import com.yangaobo.mapper.AssetsBorrowMapper;
import com.yangaobo.mapper.AssetsMapper;
import com.yangaobo.service.AssetsBorrowService;
import jakarta.annotation.Resource;
import org.springframework.cache.annotation.CacheConfig;
import org.springframework.cache.annotation.CacheEvict;
import org.springframework.cache.annotation.Cacheable;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.time.LocalDateTime;
import java.util.List;
import java.util.stream.Collectors;

/**
 * @author 杨奥博
 */
@Service
@CacheConfig(cacheNames = {"assets_borrow", "assets"})
public class AssetsBorrowServiceImpl implements AssetsBorrowService {
    @Resource
    private AssetsBorrowMapper assetsBorrowMapper;
    @Resource
    private AssetsMapper assetsMapper;

    @CacheEvict(allEntries = true)
    @Transactional(rollbackFor = Exception.class)
    @Override
    public int insert(AssetsBorrowInsertDTO dto) {
        String info = dto.getInfo();
        Long fkAssetsId = dto.getFkAssetsId();
        Integer count = dto.getCount();
        // 判断申请时间和预计归还时间
        LocalDateTime borrowTime = dto.getBorrowTime();
        LocalDateTime expectedReturnTime = dto.getExpectedReturnTime();
        if (borrowTime.isAfter(expectedReturnTime)) {
            throw new IllegalParamException("资产预计归还时间不能早于资产申请时间");
        }
        Assets assets = assetsMapper.select(fkAssetsId);
        if (ObjectUtil.isNull(assets)) {
            throw new ServerErrorException("资产不存在");
        }
        // 判断剩余库存是否充足
        Integer stock = assets.getStock();
        String stockUnit = assets.getStockUnit();
        if (count > stock) {
            throw new IllegalParamException("库存不足，仅剩" + stock + stockUnit);
        }
        // 拷贝属性
        AssetsBorrow assetsBorrow = BeanUtil.copyProperties(dto, AssetsBorrow.class);
        // 设置默认值
        assetsBorrow.setInfo(StrUtil.isBlank(info) ? "暂无描述" : info);
        assetsBorrow.setVersion(0L);
        assetsBorrow.setDeleted(0);
        assetsBorrow.setCreated(LocalDateTime.now());
        assetsBorrow.setUpdated(LocalDateTime.now());
        // DB添加：添加申请记录
        int insertResult = assetsBorrowMapper.insert(assetsBorrow);
        if (insertResult <= 0) {
            throw new ServerErrorException("DB添加失败");
        }
        // DB修改：扣减库存
        stock -= count;
        assets.setStock(stock);
        int updateResult = assetsMapper.update(assets);
        if (updateResult <= 0) {
            throw new ServerErrorException("DB修改失败");
        }
        return insertResult + updateResult;
    }

    @Cacheable(key = "#p0", condition = "#p0 != null", unless = "#result == null")
    @Override
    public AssetsBorrow select(Long id) {
        AssetsBorrow result = assetsBorrowMapper.select(id);
        if (ObjectUtil.isNull(result)) {
            throw new ServerErrorException("DB查询失败");
        }
        return result;
    }

    @Cacheable(key = "#root.methodName", unless = "#result == null")
    @Override
    public List<AssetsBorrow> list() {
        return assetsBorrowMapper.list(new AssetsBorrowPageDTO());
    }

    @Cacheable(key = "#root.methodName + ':' + #p0.toString()",
            condition = "#p0 != null",
            unless = "#result == null")
    @Override
    public PageInfo<AssetsBorrow> page(AssetsBorrowPageDTO dto) {
        PageHelper.startPage(dto.getPageNum(), dto.getPageSize());
        return new PageInfo<>(assetsBorrowMapper.list(dto));
    }

    @CacheEvict(allEntries = true)
    @Transactional(rollbackFor = Exception.class)
    @Override
    public int update(AssetsBorrowUpdateDTO dto) {
        AssetsBorrow assetsBorrow = assetsBorrowMapper.select(dto.getId());
        if (ObjectUtil.isNull(assetsBorrow)) {
            throw new ServerErrorException("DB查询失败");
        }
        BeanUtil.copyProperties(dto, assetsBorrow,
                CopyOptions.create().setIgnoreNullValue(true));
        assetsBorrow.setUpdated(LocalDateTime.now());
        int result = assetsBorrowMapper.update(assetsBorrow);
        if (result <= 0) {
            throw new ServerErrorException("DB更新失败");
        }
        return result;
    }

    @CacheEvict(allEntries = true)
    @Override
    public int delete(Long id) {
        int result = assetsBorrowMapper.delete(id);
        if (result <= 0) {
            throw new ServerErrorException("DB删除失败");
        }
        return result;
    }

    @CacheEvict(allEntries = true)
    @Override
    public int deleteBatch(List<Long> ids) {
        int result = assetsBorrowMapper.deleteBatch(ids);
        if (result <= 0) {
            throw new ServerErrorException("DB删除失败");
        }
        return result;
    }

    @Override
    public List<AssetsBorrowExcel> getExcelData() {
        return assetsBorrowMapper.list(new AssetsBorrowPageDTO())
                .stream()
                .map(assetsBorrow -> {
                    AssetsBorrowExcel assetsBorrowExcel = new AssetsBorrowExcel();
                    BeanUtil.copyProperties(assetsBorrow, assetsBorrowExcel);
                    if (ObjectUtil.isNotNull(assetsBorrow.getAssets())) {
                        assetsBorrowExcel.setAssetsTitle(assetsBorrow.getAssets().getTitle());
                    } else {
                        throw new ServerErrorException("资产不存在");
                    }
                    if (ObjectUtil.isNotNull(assetsBorrow.getEmp())) {
                        assetsBorrowExcel.setEmpName(assetsBorrow.getEmp().getRealname());
                    } else {
                        throw new ServerErrorException("员工不存在");
                    }
                    assetsBorrowExcel.setIsReturn(ObjectUtil.isNotNull(assetsBorrow.getReturnTime()) ? "已归还" : "未归还");
                    return assetsBorrowExcel;
                })
                .collect(Collectors.toList());
    }

    @CacheEvict(allEntries = true)
    @Transactional(rollbackFor = Exception.class)
    @Override
    public int returnAssets(Long id) {
        // 查询资产申请记录
        AssetsBorrow assetsBorrow = assetsBorrowMapper.select(id);
        if (ObjectUtil.isNull(assetsBorrow)) {
            throw new ServerErrorException("记录不存在");
        }
        // 查询资产信息
        Assets assets = assetsMapper.select(assetsBorrow.getFkAssetsId());
        if (ObjectUtil.isNull(assets)) {
            throw new ServerErrorException("资产不存在");
        }
        // 判断是否已归还
        if (ObjectUtil.isNotNull(assetsBorrow.getReturnTime())) {
            throw new IllegalParamException("资产已归还");
        }

        // （重复的判断是否已归还逻辑，可根据实际需求确认是否保留，这里按原文提取）
        if (ObjectUtil.isNotNull(assetsBorrow.getReturnTime())) {
            throw new IllegalParamException("资产已归还");
        }
        // DB修改：修改资产申请记录
        assetsBorrow.setReturnTime(LocalDateTime.now());
        int assetsBorrowUpdateResult = assetsBorrowMapper.update(assetsBorrow);
        if (assetsBorrowUpdateResult <= 0) {
            throw new ServerErrorException("DB资产申请记录修改失败");
        }
        // DB修改：修改资产库存
        assets.setStock(assets.getStock() + assetsBorrow.getCount());
        int assetsUpdateResult = assetsMapper.update(assets);
        if (assetsUpdateResult <= 0) {
            throw new ServerErrorException("DB资产库存修改失败");
        }

        return assetsBorrowUpdateResult + assetsUpdateResult;
    }

}
